Skip to content

fix: preserve per-knowledge-base sparse retrieval ranks and use them in rank fusion to avoid distorted ordering across independent FTS5 indexes - #9426

Merged
Soulter merged 1 commit into
AstrBotDevs:masterfrom
chinatsu1124:fix/9425-multi-kb-sparse-rank
Jul 28, 2026
Merged

fix: preserve per-knowledge-base sparse retrieval ranks and use them in rank fusion to avoid distorted ordering across independent FTS5 indexes#9426
Soulter merged 1 commit into
AstrBotDevs:masterfrom
chinatsu1124:fix/9425-multi-kb-sparse-rank

Conversation

@chinatsu1124

@chinatsu1124 chinatsu1124 commented Jul 28, 2026

Copy link
Copy Markdown

修复多个知识库各自使用独立 FTS5 索引时,直接按原始 BM25 分数合并候选导致的排序失真。

不同 FTS5 索引的 BM25 分数受各自语料规模、词频和文档长度统计影响,不能直接跨索引比较。此前合并后的位置被当作稀疏检索排名传入 RRF,可能使小知识库中的高相关结果被大知识库候选压低。

Fixes #9425

Modifications / 改动点

  • SparseResult 增加可选的来源排名 rank

  • FTS5 检索时保留候选在各知识库独立索引中的局部排名,RRF 使用该排名计算贡献。

  • 内存 BM25 回退路径仍在统一候选集上排序,并记录全局排名,保持原有语义。

  • 对未提供 rank 的旧调用保留按列表顺序计算排名的兼容行为。

  • 增加跨知识库稀疏检索和 RRF 融合回归测试,测试数据均为虚构内容。

  • This is NOT a breaking change. / 这不是一个破坏性变更。

Screenshots or Test Results / 运行截图或测试结果

验证步骤:

.venv/bin/ruff format --check astrbot/core/knowledge_base/retrieval/sparse_retriever.py astrbot/core/knowledge_base/retrieval/rank_fusion.py tests/unit/test_sparse_retriever.py tests/unit/test_rank_fusion.py
.venv/bin/ruff check astrbot/core/knowledge_base/retrieval/sparse_retriever.py astrbot/core/knowledge_base/retrieval/rank_fusion.py tests/unit/test_sparse_retriever.py tests/unit/test_rank_fusion.py
.venv/bin/python -m pytest -q tests/unit/test_sparse_retriever.py tests/unit/test_rank_fusion.py tests/test_kb_import.py tests/unit/test_kb_document_cleanup.py tests/unit/test_kb_manager_resilience.py tests/unit/test_kb_upload_atomicity.py tests/unit/test_knowledge_base_service_contract.py

结果:

4 files already formatted
All checks passed!
43 passed, 4 warnings in 129.61s

4 条警告来自既有 aiosqlite 原子性测试在线程结束时访问已关闭的事件循环,与本次改动无关。


Checklist / 检查清单

  • 😊 If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
    / 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。
  • 👀 My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
    / 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”
  • 🤓 I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
    / 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到 requirements.txtpyproject.toml 文件相应位置。
  • 😮 My changes do not introduce malicious code.
    / 我的更改没有引入恶意代码。

Summary by Sourcery

Preserve per-knowledge-base sparse retrieval ranks and use them in rank fusion to avoid distorted ordering across independent FTS5 indexes.

Bug Fixes:

  • Fix cross-knowledge-base sparse retrieval ranking by using local FTS5 ranks instead of raw BM25 scores when fusing results.
  • Ensure BM25 in-memory fallback path assigns and propagates global ranks consistently for rank fusion.

Enhancements:

  • Extend SparseResult with an optional rank field and make rank fusion backward-compatible with callers that do not provide ranks.

Tests:

  • Add unit tests to verify sparse retriever preserves per-knowledge-base FTS ranks and that rank fusion prioritizes high-relevance results from smaller knowledge bases.

@dosubot dosubot Bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Jul 28, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@lxfight lxfight left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@dosubot dosubot Bot added the lgtm This PR has been approved by a maintainer label Jul 28, 2026
@Soulter Soulter changed the title fix: 修复多知识库稀疏检索排序失真 fix: preserve per-knowledge-base sparse retrieval ranks and use them in rank fusion to avoid distorted ordering across independent FTS5 indexes Jul 28, 2026
@Soulter
Soulter merged commit b0cb91f into AstrBotDevs:master Jul 28, 2026
1 check passed
BegoniaHe added a commit to Xero-Team/AstrBot that referenced this pull request Aug 2, 2026
Preserve per-knowledge-base sparse ranks, lazy-load BM25, and reject malformed vLLM rerank responses.

Adapted from upstream commits b0cb91f (AstrBotDevs#9426), d149894 (AstrBotDevs#9435), and 894ea53 (AstrBotDevs#9454).

Upstream-Commits: b0cb91f, d149894, 894ea53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm This PR has been approved by a maintainer size:S This PR changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] 多知识库稀疏检索直接合并独立 FTS5 BM25 分数导致排序失真

3 participants